using System;
using System.Collections.Concurrent;
using System.Threading;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.I18N;

namespace OracleInternal.ServiceObjects
{
	internal class NotificationContext
	{
		internal long m_regIdFromServer;

		internal int m_payloadType;

		internal int m_payloadFlag;

		internal byte[] m_payLoad;

		internal bool m_bLastNotification;

		internal Conv m_dbCharSetConv;

		internal OracleConnectionImpl m_orclConnImpl;

		internal static bool m_bStartedNotifPropogationThread = false;

		internal static object syncObject = new object();

		internal static ConcurrentQueue<NotificationContext> m_lstOfNormalNotifs = new ConcurrentQueue<NotificationContext>();

		internal static ConcurrentQueue<NotificationContext> m_lstOfTimeoutNotifs = new ConcurrentQueue<NotificationContext>();

		internal static ManualResetEventSlim m_dataAvailableEvnt = new ManualResetEventSlim(initialState: false);

		internal static ManualResetEventSlim m_dataEnqueuedEvnt = new ManualResetEventSlim(initialState: false);

		internal NotificationContext(OracleConnectionImpl orclConnImpl, long regId, Conv dbCharSetConv, int payloadType, int payloadFlag, byte[] payload, bool bLastNotification)
		{
			m_orclConnImpl = orclConnImpl;
			m_regIdFromServer = regId;
			m_dbCharSetConv = dbCharSetConv;
			m_payloadType = payloadType;
			m_payloadFlag = payloadFlag;
			m_payLoad = payload;
			m_bLastNotification = bLastNotification;
		}

		internal static void EnqueueNotification(OracleConnectionImpl orclConnImpl, long regIdFromServer, Conv dbCharSetConv, int payloadType, int payloadFlag, byte[] rawPayload, bool bLastNotification)
		{
			NotificationContext notificationContext = new NotificationContext(orclConnImpl, regIdFromServer, dbCharSetConv, payloadType, payloadFlag, rawPayload, bLastNotification);
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.NotificationContext, OracleTraceFuncName.EnqueueNotification, "Enqueue NtfCtx Hash=" + notificationContext.GetHashCode() + " for SvrRegId=" + regIdFromServer);
			}
			m_lstOfNormalNotifs.Enqueue(notificationContext);
			if (!m_dataEnqueuedEvnt.IsSet)
			{
				m_dataEnqueuedEvnt.Set();
			}
			if (m_bStartedNotifPropogationThread)
			{
				return;
			}
			lock (syncObject)
			{
				if (!m_bStartedNotifPropogationThread)
				{
					m_bStartedNotifPropogationThread = true;
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.NotificationContext, OracleTraceFuncName.EnqueueNotification, "Spawn new thread for propagating CQN notification");
					}
					ThreadPool.QueueUserWorkItem(delegate
					{
						PropagateNotifications();
					});
				}
			}
		}

		internal static void PropagateNotifications()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.NotificationContext, OracleTraceFuncName.PropagateNotifications);
			}
			try
			{
				bool flag = false;
				while (true)
				{
					flag = false;
					NotificationContext result;
					while (!m_lstOfTimeoutNotifs.IsEmpty)
					{
						m_lstOfTimeoutNotifs.TryDequeue(out result);
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.NotificationContext, OracleTraceFuncName.EnqueueNotification, "Process Timeout NtfCtx Hash=" + result.GetHashCode() + " for SvrRegId=" + result.m_regIdFromServer + " and propagate to client app");
						}
						OracleNotificationManager.s_sendNtfDetailsToUpperLayer(result);
						flag = true;
					}
					if (!m_lstOfNormalNotifs.IsEmpty)
					{
						m_lstOfNormalNotifs.TryDequeue(out result);
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131328, OracleTraceClassName.NotificationContext, OracleTraceFuncName.EnqueueNotification, "Process NtfCtx Hash=" + result.GetHashCode() + " for SvrRegId=" + result.m_regIdFromServer + " and propagate to client app");
						}
						OracleNotificationManager.s_sendNtfDetailsToUpperLayer(result);
						flag = true;
					}
					if (flag)
					{
						continue;
					}
					m_dataEnqueuedEvnt.Reset();
					if (m_lstOfNormalNotifs.Count == 0 && m_lstOfTimeoutNotifs.Count == 0)
					{
						m_dataEnqueuedEvnt.Wait();
						if (m_lstOfNormalNotifs.Count == 0 && m_lstOfTimeoutNotifs.Count == 0)
						{
							break;
						}
					}
					else
					{
						m_dataEnqueuedEvnt.Set();
					}
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.NotificationContext, OracleTraceFuncName.PropagateNotifications, ex);
			}
			finally
			{
				m_bStartedNotifPropogationThread = false;
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)131584, OracleTraceClassName.NotificationContext, OracleTraceFuncName.PropagateNotifications);
				}
			}
		}
	}
}
